package com.fine.hair.applet.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fine.hair.applet.mapper.BranchMapper;
import com.fine.hair.applet.mapper.OrderMapper;
import com.fine.hair.applet.mapper.UserMapper;
import com.fine.hair.applet.service.BranchService;
import com.fine.hair.comm.dto.BranchSimpleInfoDto;
import com.fine.hair.comm.dto.ServicedStaffDto;
import com.fine.hair.comm.dto.StaffListDto;
import com.fine.hair.comm.dto.StaffMienDto;
import com.fine.hair.comm.enums.StatusType;
import com.fine.hair.comm.exception.BusinessException;
import com.fine.hair.comm.model.Branch;
import com.fine.hair.comm.model.Order;
import com.fine.hair.comm.model.User;
import com.fine.hair.comm.pojo.BranchSimpleInfo;
import com.fine.hair.comm.pojo.StaffSimpleInfo;
import com.fine.hair.comm.utils.PageInfo;
import com.fine.hair.comm.vo.BranchSimpleInfoVo;
import com.fine.hair.comm.vo.StaffMienVo;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>${Description}</p>
 *
 * @author mouseyCat
 * @date 2020/10/4 15:12
 */
@Service
public class BranchServiceImpl extends ServiceImpl<BranchMapper, Branch> implements BranchService {

    @Resource
    private BranchMapper branchMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private OrderMapper orderMapper;

    @Override
    public List<StaffMienVo> staffMien(StaffMienDto dto) {
        List<StaffMienVo> staffMienList = Lists.newArrayList();
        List<Branch> branchList;
        if (StrUtil.isNotBlank(dto.getAreaOrServiceOrBranchName())) {
            branchList = branchMapper.selectByKey(dto.getAreaOrServiceOrBranchName());
        } else {
            branchList = branchMapper.selectList(new LambdaQueryWrapper<>());
        }

        List<Order> orderList = orderMapper.selectList(new LambdaQueryWrapper<Order>().eq(Order::getUserId, dto.getUserId()));
        List<String> technicianIds = orderList.stream().map(Order::getTechnicianId).collect(Collectors.toList());
        StaffMienVo vo;
        for (Branch branch : branchList) {
            vo = new StaffMienVo();
            BeanUtil.copyProperties(branch, vo);
            vo.setBranchId(branch.getId().toString());
            vo.setBranchName(branch.getTitle());
            vo.setBranchImage(branch.getImages().split(Constants.COMMA)[0]);
            List<StaffSimpleInfo> list = userMapper.selectByBranchId(branch.getId());
            List<StaffSimpleInfo> StaffSimpleInfoList = Lists.newArrayList();
            for (String technicianId : technicianIds) {
                for (StaffSimpleInfo staffSimpleInfo : list) {
                    // 《新需求》只添加 服务过该用户的员工
                    if (technicianId.equals(staffSimpleInfo.getTechnicianId())){
                        StaffSimpleInfoList.add(staffSimpleInfo);
                    }
                    break;
                }
            }
            vo.setStaffList(StaffSimpleInfoList);
            staffMienList.add(vo);
        }
        return staffMienList;
    }

    private PageInfo<StaffSimpleInfo> getStaffSimpleInfoPageInfo(Integer pageCurr, Integer pageSize, Long branchId) {
        // 查询该门店下的技师
        PageInfo<StaffSimpleInfo> pageInfo = new PageInfo<>(pageCurr, pageSize);
        List<StaffSimpleInfo> list = userMapper.selectByBranchIdAndPageInfo(branchId, pageInfo);
        for (StaffSimpleInfo staffSimpleInfo : list) {
            if (staffSimpleInfo.getScore() == null) {
                staffSimpleInfo.setScore("暂无评分");
            }
            if (staffSimpleInfo.getResume() == null) {
                staffSimpleInfo.setResume("暂无");
            }
        }
        pageInfo.setRecords(list);
        return pageInfo;
    }

    @Override
    public PageInfo<BranchSimpleInfo> branchSimpleInfo(BranchSimpleInfoDto dto) {
        PageInfo<Branch> pageInfo = new PageInfo<>(dto.getPageCurr(), dto.getPageSize());
        // 查询所有门店
        IPage<Branch> branchIPage = branchMapper.selectPage(pageInfo,
                new LambdaQueryWrapper<Branch>().eq(Branch::getStatus,
                StatusType.NORMAL.getCode()));

        List<Branch> branches = branchIPage.getRecords();

        List<BranchSimpleInfo> vos = Lists.newArrayList();
        for (Branch branch : branches) {
            BranchSimpleInfo vo = new BranchSimpleInfo();
            BeanUtils.copyProperties(branch, vo);
            vo.setBranchId(branch.getId().toString());
            vo.setImages(branch.getImages().split(Constants.COMMA)[0]);
            GlobalCoordinates source = new GlobalCoordinates(dto.getBranchLat(), dto.getBranchLng());
            GlobalCoordinates target = new GlobalCoordinates(branch.getLat(), branch.getLng());
            vo.setDistance(getDistanceMeter(source, target, Ellipsoid.Sphere));
            vos.add(vo);
        }

        vos.sort(Comparator.comparingDouble(BranchSimpleInfo::getDistance));

        PageInfo<BranchSimpleInfo> voPage = new PageInfo<>(dto.getPageCurr(), dto.getPageSize());
        voPage.setRecords(vos);
        voPage.setHasNextPage(pageInfo.getHasNextPage());
        voPage.setHasPrevPage(pageInfo.getHasPrevPage());
        voPage.setStartIndex(pageInfo.getStartIndex());
        voPage.setTotal(pageInfo.getTotal());
        voPage.setPages(pageInfo.getPages());

        BranchSimpleInfoVo vo = new BranchSimpleInfoVo();

        return voPage;
    }

    @Override
    public PageInfo<StaffSimpleInfo> staffList(StaffListDto dto) {
        PageInfo<StaffSimpleInfo> pageInfo = getStaffSimpleInfoPageInfo(dto.getPageCurr(), dto.getPageSize(), dto.getBranchId());
        return pageInfo;
    }

    @Override
    public PageInfo<StaffSimpleInfo> servicedStaff(ServicedStaffDto dto) {
        User user = userMapper.selectById(dto.getUserId());
        if(Objects.isNull(user)){
            throw new BusinessException("当前技师不存在");
        }
        if( StringUtils.isBlank(user.getPutBranchId())){
            throw new BusinessException("当前技师未挂店");
        }
        List<Order> orderList = orderMapper.selectList(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, dto.getUserId())
        .eq(Order::getBranchId, user.getPutBranchId()));
        List<String> technicianIds = orderList.stream().map(Order::getTechnicianId).distinct().collect(Collectors.toList());
        PageInfo<StaffSimpleInfo> pageInfo = new PageInfo<>(dto.getPageCurr(), dto.getPageSize());
        if (technicianIds.size() < 1) {
            return pageInfo;
        }
        List<StaffSimpleInfo> staffSimpleInfo = userMapper.selectByTechnicianId(pageInfo, technicianIds);
        pageInfo.setRecords(staffSimpleInfo);
        return pageInfo;
    }

    private static double getDistanceMeter(GlobalCoordinates gpsFrom, GlobalCoordinates gpsTo, Ellipsoid
            ellipsoid) {

        // 创建GeodeticCalculator，调用计算方法，传入坐标系、经纬度用于计算距离
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid, gpsFrom, gpsTo);

        // 结果保留两位小数
        return (double) Math.round(geoCurve.getEllipsoidalDistance() * 100 / 1000) / 100;
    }
}

